home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / urt / amiga_extras / getami / getami.c next >
Encoding:
C/C++ Source or Header  |  1994-04-01  |  27.6 KB  |  1,185 lines

  1. /* 
  2.  * getami.c - display a Utah RLE picture on a Commodore Amiga
  3.  * 
  4.  * Authors:    Eleftherios Koutsofios (ek@ulysses.att.com)
  5.  *        Kriton Kyrimis (kyrimis%theseas@csi.forth.gr)
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <intuition/intuition.h>
  10. #include <libraries/dos.h>
  11. #include <libraries/asl.h>
  12. #include <utility/tagitem.h>
  13. #include <exec/types.h>
  14. #include <exec/memory.h>
  15. #include <graphics/gfxbase.h>
  16. #include <graphics/view.h>
  17. #include <utility/tagitem.h>
  18. #ifndef NOIFFLIB
  19. #include <iff.h>
  20. #endif
  21. #include <rle.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <signal.h>
  25. #ifdef __SASC
  26. #include <proto/intuition.h>
  27. #include <proto/graphics.h>
  28. #include <proto/dos.h>
  29. #include <proto/exec.h>
  30. #include <proto/asl.h>
  31. #endif
  32. #ifdef __GNUC__
  33. #include <inline/intuition.h>
  34. #include <inline/graphics.h>
  35. #include <inline/dos.h>
  36. #include <inline/exec.h>
  37. #include <inline/asl.h>
  38. #endif
  39.  
  40. #ifdef __SASC
  41. extern  void __asm MultiPlot(register __a0 struct Window *,
  42.                  register __d0 WORD,
  43.                  register __d1 WORD,
  44.                  register __d2 WORD);
  45. #else
  46. #ifdef __GNUC__
  47. static __inline void
  48. MP(struct Window *w, WORD x, WORD y, WORD c)
  49. {
  50.   register struct Window *a0 __asm("a0") = w;
  51.   register long d0 __asm("d0") = x;
  52.   register long d1 __asm("d1") = y;
  53.   register long d2 __asm("d2") = c;
  54.   __asm __volatile ("jsr _MultiPlot"
  55.   : /* no output */
  56.   : "r" (a0), "r" (d0), "r" (d1), "r" (d2)
  57.   : "a0", "a1", "d0", "d1", "d2", "memory");
  58. }
  59. #define MultiPlot MP
  60. #else
  61. #define NOASM
  62. #endif
  63. #endif
  64.  
  65. #define MIN(x, y) ((x) < (y) ? (x) : (y))
  66. #define ABS(x) ((x) >= 0 ? (x) : -(x))
  67. #define MAX(x,y) ((x) > (y) ? (x) : (y))
  68. #define cindex(r, g, b) ((((r) >> 4) << 8) | (((g) >> 4) << 4) | ((b) >> 4))
  69. #define rdist(a, b) \
  70.   ((ABS (((cusage[a].i >> 8) & 0xf) - ((cusage[b].i >> 8) & 0xf))) * 30)
  71. #define gdist(a, b) \
  72.   ((ABS (((cusage[a].i >> 4) & 0xf) - ((cusage[b].i >> 4) & 0xf))) * 59)
  73. #define bdist(a, b) \
  74.   ((ABS ((cusage[a].i & 0xf) - (cusage[b].i & 0xf))) * 11)
  75. #define mapx(x) (x + offsetx)
  76. #define mapy(y) (sh - (y) - 1 - offsety)
  77. #define fmapy(y) (y + offsety)
  78. #define inside(x, y) ((x) >= 0 && (y) >= 0 && (x) < sw && (y) < sh)
  79. #define EXACT(x) (x)
  80. #define RED(x) ((2 << 4) | x)
  81. #define GREEN(x) ((3 << 4) | x)
  82. #define BLUE(x) ((1 << 4) | x)
  83.  
  84. static
  85. #ifdef __GNUC__
  86. __inline
  87. #endif
  88. long SQ(long x)
  89. {
  90.   return x * x;
  91. }
  92.  
  93. #define MAX_X 362
  94. #define MAX_Y_NTSC 241
  95. #define MAX_Y_PAL 283
  96.  
  97. #ifdef LIBRARY_VERSION    /* AmigaDOS 1.3 or earlier */
  98. #define BASENAME(x)    (strrchr((x),'/') ? strrchr((x),'/')+1 : \
  99.             (strrchr((x),':') ? strrchr((x),':')+1 : (x)))
  100. #else
  101. #define BASENAME(x) FilePart(x)
  102. #endif
  103.  
  104. struct GfxBase       *GfxBase = NULL;
  105. struct IntuitionBase *IntuitionBase = NULL;
  106. #ifndef NOIFFLIB
  107. struct Library *IFFBase = NULL;
  108. #endif
  109. struct Library *AslBase = NULL;
  110.  
  111. static struct NewScreen screen = {
  112.   0, 0, 0, 0, 6, 0, 1, 0, AUTOSCROLL | CUSTOMSCREEN, NULL, "GetAmi", NULL, NULL
  113. };
  114.  
  115. UWORD DriPens[] = { (UWORD)~0 };
  116.  
  117. static struct TagItem ScreenTags[] = {
  118. #define DISPIDTAG 0
  119.   {SA_DisplayID, NULL},
  120.   {SA_Overscan, OSCAN_VIDEO},
  121.   {SA_Pens, (ULONG)DriPens},
  122.   {TAG_DONE, NULL}
  123. };
  124.  
  125. static struct Image img = {
  126.   0, 0, 10, 10, 0, NULL, 0, 0, NULL
  127. };
  128.  
  129. static struct Gadget CloseGadget = {
  130.   NULL, 0, 0, 10, 10, GADGHCOMP | GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&img,
  131.   NULL, NULL, 0, NULL, 1, NULL
  132. };
  133.  
  134. static struct NewWindow window = {
  135.   0, 0, 0, 0, 0, 1, GADGETUP | MENUPICK | MENUVERIFY,
  136.   SMART_REFRESH | BACKDROP | BORDERLESS,
  137.   &CloseGadget, NULL, NULL, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN
  138. };
  139.  
  140. struct TagItem FileReqTags[] = {
  141. #define WINTAG 0
  142.   {ASLFR_Window, NULL},
  143.   {ASLFR_SleepWindow, TRUE},
  144.   {ASLFR_TitleText, (ULONG)"File name"},
  145.   {ASLFR_DoSaveMode, TRUE},
  146.   {ASLFR_RejectIcons, TRUE},
  147.   {TAG_DONE, NULL}
  148. };
  149.  
  150. static struct cuse {
  151.   int i, j;
  152. } cusage[4096];
  153.  
  154. static struct Window   *w1  = NULL, *w2 = NULL, *w3 = NULL;
  155. static struct RastPort *rp1 = NULL, *rp2 = NULL, *rp3 = NULL;
  156. static struct Screen   *s1 = NULL;
  157. static struct Screen   *s2 = NULL;
  158. static struct Screen   *s3 = NULL;
  159. static struct ViewPort *vp1 = NULL, *vp2 = NULL, *vp3 = NULL;
  160. static rle_pixel       *sl[3];
  161. static rle_pixel      **cmap;
  162. static unsigned int     R[32], G[32], B[32];
  163. static char            *tfile, *infile = NULL;
  164. static FILE            *ifd = NULL, *tfd = NULL;
  165. static int              width, height, depth, nused, sw, sh, sd, isham;
  166. #if 0
  167. static int        nleft;
  168. #endif
  169. static int              offsetx, offsety;
  170. static int        bw=0, threescreens=0, havemenu=0, flip=0;
  171. static int        forceham=0, haveoldpri=0;
  172. static long        oldpri;
  173.  
  174. static USHORT *Ptr = NULL;
  175.  
  176. static USHORT RenderPtr[] = {
  177.   0x0000, 0x0000,
  178.   0x7800, 0x3800,
  179.   0x7000, 0x9000,
  180.   0x7800, 0x8800,
  181.   0x5C00, 0xA400,
  182.   0x0E00, 0x1200,
  183.   0x0700, 0x0900,
  184.   0xC300, 0xC400,
  185.   0xADD1, 0xADD1,
  186.   0xA955, 0xA955,
  187.   0xC9FF, 0xC9FF,
  188.   0x0000, 0x0000,
  189.   0x0BB8, 0x0BB8,
  190.   0x0AA8, 0x0AA8,
  191.   0x0AB8, 0x0AB8,
  192.   0x0008, 0x0008,
  193.   0x0038, 0x0038,
  194.   0x0000, 0x0000
  195. };
  196.  
  197. extern char *mktemp(char *);
  198.  
  199. UBYTE handleIDCMP (void);
  200.  
  201. #define MENUITEMS 3
  202.  
  203. static struct IntuiText txt[] = {
  204.   { 0, 1, JAM1, 0, 0, NULL, "Save", NULL },
  205.   { 0, 1, JAM1, 0, 0, NULL, "Save As", NULL },
  206.   { 0, 1, JAM1, 0, 0, NULL, "Quit", NULL }
  207. };
  208.  
  209. static struct MenuItem actions[] = {
  210.   { &actions[1], 0, 0, 68, 8, ITEMTEXT | ITEMENABLED | HIGHBOX | COMMSEQ, 0,
  211.     (APTR)&txt[0], NULL, 'S', NULL, MENUNULL
  212.   },
  213.   { &actions[2], 0, 10, 68, 8, ITEMTEXT | ITEMENABLED | HIGHBOX | COMMSEQ, 0,
  214.     (APTR)&txt[1], NULL, 'A', NULL, MENUNULL
  215.   },
  216.   { NULL, 0, 20, 68, 8, ITEMTEXT | ITEMENABLED | HIGHBOX | COMMSEQ, 0,
  217.     (APTR)&txt[2], NULL, 'Q', NULL, MENUNULL
  218.   }
  219. };
  220.  
  221. static struct Menu menu = {
  222.   NULL, 10, 0, 64, 0, MENUENABLED, "Actions", &actions[0]
  223. };
  224.  
  225. static char fnam[80] = {'\0'};
  226.  
  227. int compare (struct cuse *, struct cuse *);
  228. int find_most_used (void);
  229. int display_rle (void);
  230. void show_rgb (void);
  231. void finish(void);
  232. void save(void);
  233. void FixColors(void);
  234. void ResetColors(void);
  235. void GetFile(void);
  236. int CalcWidth(int);
  237. int CalcHAMWidth(int);
  238. int CalcHeight(int, int);
  239. extern int IsPAL(void);
  240.  
  241. #ifdef NOASM
  242. long curcol1, curcol2, curcol3;
  243.  
  244. #define OptSetAPen1(rp, col) curcol1 = (col); if(curcol1) SetAPen((rp), curcol1)
  245. #define OptSetAPen2(rp, col) curcol2 = (col); if(curcol2) SetAPen((rp), curcol2)
  246. #define OptSetAPen3(rp, col) curcol3 = (col); if(curcol3) SetAPen((rp), curcol3)
  247.  
  248. #define OptWritePixel1(rp, x, y) if(curcol1) WritePixel((rp), (x), (y))
  249. #define OptWritePixel2(rp, x, y) if(curcol2) WritePixel((rp), (x), (y))
  250. #define OptWritePixel3(rp, x, y) if(curcol3) WritePixel((rp), (x), (y))
  251. #endif
  252.  
  253. int
  254. main(int argc, char **argv)
  255. {
  256.   int i, SW=0, SH=0, dump=0, load=0;
  257.   ULONG signalmask, signals;
  258.   UBYTE done;
  259.   BYTE pal;
  260.   FILE *f;
  261.   struct Preferences prefs;
  262.   extern char *optarg;
  263.   extern int optind;
  264.  
  265.   (void)signal(SIGINT, (void (*) (int))finish);
  266.   while ((i = getopt(argc, argv, "w:h:o:dlb3fH")) != EOF) {
  267.     switch(i) {
  268.       case 'w':
  269.         SW = atoi(optarg);
  270.         break;
  271.       case 'h':
  272.         SH = atoi(optarg);
  273.         break;
  274.       case 'o':
  275.         strcpy(fnam, optarg);
  276.         break;
  277.       case 'd':
  278.         dump = 1;
  279.         break;
  280.       case 'l':
  281.         load = 1;
  282.         break;
  283.       case 'b':
  284.         bw = 1;
  285.         forceham = 0;
  286.         threescreens = 0;
  287.         break;
  288.       case '3':
  289.         threescreens = 1;
  290.         bw = 0;
  291.         forceham = 0;
  292.         break;
  293.       case 'f':
  294.         flip = 1;
  295.         break;
  296.       case 'H':
  297.         forceham = 1;
  298.         bw = 0;
  299.         threescreens = 0;
  300.         break;
  301.       case '?':
  302.       default:
  303.         fprintf(stderr,
  304.       "Usage: %s [-dlfb3H] [-w width] [-h height] [-o IFFfile] [file]\n",
  305.       BASENAME(argv[0]));
  306.         exit(1);
  307.     }
  308.   }
  309.  
  310.   if (optind >= argc)
  311.     ifd = stdin;
  312.   else{
  313.     infile = argv[optind];
  314.     if ((ifd = fopen (infile, "r")) == NULL)
  315.       fprintf (stderr, "cannot open input file %s\n", infile), finish();
  316.   }
  317.  
  318.   if ((tfile = mktemp ("t:rle.XXX")) == NULL)
  319.     fprintf (stderr, "cannot create a temp name for tfile\n"), finish();
  320.  
  321.   if ((tfd = fopen (tfile, "w+")) == NULL)
  322.       fprintf (stderr, "cannot open output file %s\n", tfile), finish();
  323.  
  324.   if ((GfxBase =
  325.        (struct GfxBase *) OpenLibrary ("graphics.library", 0L)) == NULL)
  326.      fprintf (stderr, "Can't open graphics.library\n"), finish();
  327.  
  328.   if ((IntuitionBase = (struct IntuitionBase *)
  329.        OpenLibrary ("intuition.library", 0L)) == NULL)
  330.     fprintf (stderr, "Can't open intuition.library\n"), finish();
  331.  
  332. #ifndef NOIFFLIB
  333.   if ((IFFBase = OpenLibrary(IFFNAME, IFFVERSION)) == NULL) {
  334. #endif
  335.     actions[0].Flags &= ~ITEMENABLED;
  336.     actions[1].Flags &= ~ITEMENABLED;
  337. #ifndef NOIFFLIB
  338.   }
  339. #endif
  340.   if ((AslBase = OpenLibrary("asl.library", 0L)) == NULL) {
  341.     actions[1].Flags &= ~ITEMENABLED;
  342.   }
  343.  
  344.   pal = IsPAL();
  345.  
  346.   if (find_most_used () == -1)
  347.     fprintf (stderr, "error in find_most_used\n"), finish();
  348.  
  349.   if (load) {
  350.     f = fopen("cmap", "r");
  351.     if (!f) {
  352.       fprintf(stderr, "Can't find cmap file\n");
  353.     }else{
  354.       fread((char *)R, sizeof(R), 1, f);
  355.       fread((char *)G, sizeof(G), 1, f);
  356.       fread((char *)B, sizeof(B), 1, f);
  357.     }
  358.     fclose(f);
  359.   }
  360.   if (dump) {
  361.     f = fopen("cmap", "w");
  362.     if (!f) {
  363.       fprintf(stderr, "Can't create cmap file\n");
  364.     }else{
  365.       fwrite((char *)R, sizeof(R), 1, f);
  366.       fwrite((char *)G, sizeof(G), 1, f);
  367.       fwrite((char *)B, sizeof(B), 1, f);
  368.     }
  369.     fclose(f);
  370.   }
  371.   fseek (tfd, 0L, 0);
  372.  
  373.   if (!forceham && (bw || threescreens || nused <= 32)) {
  374.     isham = FALSE;
  375.     sw = CalcWidth(width);
  376.     sh = CalcHeight(height, pal);
  377.     if (nused > 16) sd = 5;
  378.     else if (nused > 8) sd = 4;
  379.     else if (nused > 4) sd = 3;
  380.     else if (nused > 2) sd = 2;
  381.     else if (nused > 0) sd = 1;
  382.     else
  383.       fprintf (stderr, "found 0!! colors\n"), finish();
  384.     if (SW) sw = SW;
  385.     if (SH) sh = SH;
  386.     screen.Width = sw, screen.Height = sh, screen.Depth = sd;
  387.     if (pal) {
  388.       screen.ViewModes =
  389.     ((sh > MAX_Y_PAL) ? LACE : 0) | ((sw > MAX_X) ? HIRES : 0);
  390.     }else{
  391.       screen.ViewModes =
  392.     ((sh > MAX_Y_NTSC) ? LACE : 0) | ((sw > MAX_X) ? HIRES : 0);
  393.     }
  394.     window.Width = sw, window.Height = sh;
  395.   } else {
  396.     isham = TRUE;
  397.     sd = 6;
  398.     sw = CalcHAMWidth(width);
  399.     sh = CalcHeight(height, pal);
  400.     if (SW) sw = SW;
  401.     if (SH) sh = SH;
  402.     screen.Width = sw, screen.Height = sh, screen.Depth = sd;
  403.     if (pal) {
  404.       screen.ViewModes = ((sh > MAX_Y_PAL) ? LACE : 0) | HAM;
  405.     }else{
  406.       screen.ViewModes = ((sh > MAX_Y_NTSC) ? LACE : 0) | HAM;
  407.     }
  408.     window.Width = sw, window.Height = sh;
  409.   }
  410.   ScreenTags[DISPIDTAG].ti_Data = screen.ViewModes;
  411.   if (pal) {
  412.     ScreenTags[DISPIDTAG].ti_Data |= PAL_MONITOR_ID;
  413.   }else{
  414.     ScreenTags[DISPIDTAG].ti_Data |= NTSC_MONITOR_ID;
  415.   }
  416.  
  417.   for (i=0; i<MENUITEMS; i++) {
  418.       if (screen.ViewModes & HIRES) {
  419.     actions[i].Width += COMMWIDTH;
  420.       }else{
  421.     actions[i].Width += LOWCOMMWIDTH;
  422.       }
  423.     }
  424.  
  425.     GetPrefs(&prefs, sizeof(prefs));
  426.     Ptr = (USHORT *)AllocMem(POINTERSIZE * sizeof(USHORT), MEMF_CHIP);
  427.     if (!Ptr) {
  428.       fprintf (stderr, "Can't allocate chip memory for pointer\n");
  429.       finish();
  430.     }
  431.       
  432.     if (threescreens) {
  433.       if ((s3 = OpenScreenTagList (&screen, ScreenTags)) == NULL)
  434.     fprintf (stderr, "Can't open screen 3\n"), finish();
  435.       ShowTitle (s3, FALSE);
  436.       window.Screen = s3;
  437.       if ((w3 = OpenWindow (&window)) == NULL)
  438.     fprintf (stderr, "Can't open window 3\n"), finish();
  439.       vp3 = &(s3->ViewPort);
  440.       rp3 = w3->RPort;
  441.       SetMenuStrip(w3, &menu);
  442.  
  443.       if ((s2 = OpenScreenTagList (&screen, ScreenTags)) == NULL)
  444.     fprintf (stderr, "Can't open screen 2\n"), finish();
  445.       ShowTitle (s2, FALSE);
  446.       window.Screen = s2;
  447.       if ((w2 = OpenWindow (&window)) == NULL)
  448.     fprintf (stderr, "Can't open window 2\n"), finish();
  449.     vp2 = &(s2->ViewPort);
  450.     rp2 = w2->RPort;
  451.     SetMenuStrip(w2, &menu);
  452.   }
  453.   if ((s1 = OpenScreenTagList (&screen, ScreenTags)) == NULL)
  454.     fprintf (stderr, "Can't open screen 1\n"), finish();
  455.   ShowTitle (s1, FALSE);
  456.   window.Screen = s1;
  457.   if ((w1 = OpenWindow (&window)) == NULL)
  458.     fprintf (stderr, "Can't open window 1\n"), finish();
  459.   vp1 = &(s1->ViewPort);
  460.   rp1 = w1->RPort;
  461.   SetMenuStrip(w1, &menu);
  462.  
  463.   if (isham) nused = 16;
  464.   for (i = 0; i < nused; i++) {
  465.     if (threescreens) {
  466.       SetRGB4 (vp1, (long) i, (long) i, 0L, 0L);
  467.       SetRGB4 (vp2, (long) i, 0L, (long) i, 0L);
  468.       SetRGB4 (vp3, (long) i, 0L, 0L, (long) i);
  469.     }else{
  470.       SetRGB4 (vp1, (long) i, (long) R[i], (long) G[i], (long) B[i]);
  471.     }
  472.   }
  473.  
  474.   memcpy(Ptr, RenderPtr, POINTERSIZE * sizeof(USHORT));
  475.   SetPointer(w1, Ptr, 16, 16, -1, 0);
  476.   if (threescreens) {
  477.     SetPointer(w2, Ptr, 16, 16, -1, 0);
  478.     SetPointer(w3, Ptr, 16, 16, -1, 0);
  479.   }
  480.  
  481.   display_rle ();
  482.  
  483.   memcpy(Ptr, prefs.PointerMatrix, POINTERSIZE * sizeof(USHORT));
  484.   SetPointer(w1, Ptr, 16, 16, -1 + prefs.XOffset, prefs.YOffset);
  485.   if (threescreens) {
  486.     SetPointer(w2, Ptr, 16, 16, -1 + prefs.XOffset, prefs.YOffset);
  487.     SetPointer(w3, Ptr, 16, 16, -1 + prefs.XOffset, prefs.YOffset);
  488.   }
  489.   
  490.   if (fnam[0]) {
  491. #ifndef NOIFFLIB
  492.     if (IFFBase) save();
  493. #else
  494.     save();
  495. #endif
  496.   }else{
  497.     done = (UBYTE)0;
  498.     if (threescreens) {
  499.       signalmask = (1L << w1->UserPort->mp_SigBit) |
  500.            (1L << w2->UserPort->mp_SigBit) |
  501.            (1L << w3->UserPort->mp_SigBit);
  502.     }else{
  503.       signalmask = 1L << w1->UserPort->mp_SigBit;
  504.     }
  505.  
  506.     if (threescreens) {    /* Run at high priority to reduce flicker */
  507.       haveoldpri = 1;
  508.       oldpri = SetTaskPri(FindTask(0L), 19L);
  509.     }
  510.     while (!done) {
  511.       if (threescreens) {
  512.         if (!havemenu) {
  513.           ScreenToFront(s1);
  514.         }
  515.         done = handleIDCMP();
  516.         if (!havemenu) {
  517.       ScreenToFront(s2);
  518.         }
  519.         done |= handleIDCMP();
  520.         if (!havemenu) {
  521.           ScreenToFront(s3);
  522.         }
  523.         done |= handleIDCMP();
  524.       }
  525.       if (!threescreens || havemenu) {
  526.         signals = Wait(signalmask);
  527.         if (signals & signalmask) {
  528.           done = handleIDCMP();
  529.         }
  530.       }
  531.     }
  532.   }
  533.   finish();
  534. #ifdef __SASC
  535.   return 0;
  536. #endif
  537. }
  538.  
  539. int
  540. compare (struct cuse *a, struct cuse *b)
  541. {
  542.   if (a->j < b->j)
  543.     return 1;
  544.   else if (a->j > b->j)
  545.     return -1;
  546.   else
  547.     return 0;
  548. }
  549.   
  550. int
  551. find_most_used (void)
  552. {
  553.   rle_hdr  rle_f_hdr;
  554.   char               comi[4][100];
  555.   char              *como;
  556.   unsigned char      r, g, b;
  557.   int             ncolors, i, j, x, packed, pix, col;
  558.  
  559.   rle_f_hdr.rle_file = ifd;
  560.   if (rle_get_setup(&rle_f_hdr) < 0)
  561.     return -1;
  562.  
  563.   RLE_CLR_BIT (rle_f_hdr, RLE_ALPHA);
  564.   for (i = 3; i < rle_f_hdr.ncolors; i++)
  565.     RLE_CLR_BIT (rle_f_hdr, i);
  566.  
  567.   ncolors = rle_f_hdr.ncolors > 3 ? 3 : rle_f_hdr.ncolors;
  568.   if (ncolors == 2)
  569.     return -1;
  570.  
  571.   height = rle_f_hdr.ymax - rle_f_hdr.ymin + 1;
  572.   width  = rle_f_hdr.xmax - rle_f_hdr.xmin + 1;
  573.  
  574.   depth = 0, packed = 0;
  575.   if ((como = rle_getcom ("cy_depth", &rle_f_hdr)) != NULL) {
  576.     depth = atoi (como);
  577.     if ((como = rle_getcom ("cy_width", &rle_f_hdr)) != NULL)
  578.       width = atoi (como);
  579.     como = rle_getcom ("cy_packed", &rle_f_hdr);
  580.     packed = como ? 1 : 0;
  581.   }
  582.   if (!depth)
  583.     depth = ncolors * 8;
  584.  
  585.   for (i = 0; i < 3; i++)
  586.     if ((sl[i] = (rle_pixel *) malloc(rle_f_hdr.xmax -
  587.                                       rle_f_hdr.xmin + 1)) == NULL) {
  588.       for (j = 0; j < i; j++)
  589.         free ((char *) sl[j]);
  590.       return -1;
  591.     }
  592.  
  593.   rle_f_hdr.xmax -= rle_f_hdr.xmin, rle_f_hdr.xmin = 0;
  594.  
  595.   rle_dflt_hdr.dispatch   = RUN_DISPATCH;
  596.   rle_dflt_hdr.alpha      = 0;
  597.   rle_dflt_hdr.background = rle_f_hdr.background;
  598.   rle_dflt_hdr.ncmap      = rle_f_hdr.ncmap;
  599.   rle_dflt_hdr.cmaplen    = rle_f_hdr.cmaplen;
  600.   rle_dflt_hdr.cmap       = rle_f_hdr.cmap;
  601.   rle_dflt_hdr.comments   = NULL;
  602.   rle_dflt_hdr.rle_file       = tfd;
  603.   rle_dflt_hdr.xmin       = 0;
  604.   rle_dflt_hdr.xmax       = width  - 1;
  605.   rle_dflt_hdr.ymin       = 0;
  606.   rle_dflt_hdr.ymax       = height - 1;
  607.   rle_dflt_hdr.ncolors    = ncolors;
  608.   for (i = 0; i < MIN (3, ncolors); i++)
  609.     RLE_SET_BIT (rle_dflt_hdr, i);
  610.   for (i = MIN (3, ncolors); i < ncolors; i++)
  611.     RLE_CLR_BIT (rle_dflt_hdr, i);
  612.   RLE_CLR_BIT (rle_dflt_hdr, RLE_ALPHA);
  613.  
  614.   if (packed) {
  615.     sprintf (comi[0], "cy_depth=%d", depth), rle_putcom (comi[0], &rle_dflt_hdr);
  616.     sprintf (comi[1], "cy_width=%d", width), rle_putcom (comi[1], &rle_dflt_hdr);
  617.     strcpy (comi[2], "cy_packed=1"),         rle_putcom (comi[2], &rle_dflt_hdr);
  618.   }
  619.  
  620.   cmap = buildmap (&rle_f_hdr, 3, 1.0, 0.0);
  621.  
  622.   rle_put_setup (&rle_dflt_hdr);
  623.  
  624.   while (rle_getrow(&rle_f_hdr, sl) <= rle_f_hdr.ymax) {
  625.     rle_putrow (sl, width, &rle_dflt_hdr);
  626.     if (ncolors == 3) {
  627.       for (x = 0; x < width; x++)
  628.         r = sl[0][x], g = sl[1][x], b = sl[2][x], cusage[cindex(r, g, b)].j++;
  629.     } else if (ncolors == 1 && !packed) {
  630.       for (x = 0; x < width; x++) {
  631.         r = cmap[0][sl[0][x]];
  632.     g = cmap[1][sl[0][x]];
  633.     b = cmap[2][sl[0][x]];
  634.     cusage[cindex(r, g, b)].j++;
  635.       }
  636.     } else {
  637.       for (col = 0, x = 0; x < width; col = (col + 1) & 7, x++) {
  638.         pix = (sl[0][x / 8] & (1 << (7 - col))) ? 0: 255;
  639.         r = pix, g = pix, b = pix, cusage[cindex(r, g, b)].j++;
  640.       }
  641.     }
  642.   }
  643.   for (i = 0; i < 3; i++)
  644.     free((char *) sl[i]);
  645.  
  646.   nused = 0;
  647.   for (i = 0; i < 4096; i++) {
  648.     cusage[i].i = i;
  649.     if (cusage[i].j)
  650.       nused++;
  651.   }
  652.   printf ("colors used: %d\n", nused);
  653.  
  654.   qsort ((char *) cusage, 4096, sizeof (struct cuse), compare);
  655.  
  656.   if (threescreens) {
  657.     nused = 16;
  658.     return 0;
  659.   }
  660.   if (bw) {
  661.     for (i = 0; i < 16; i++) {
  662.       R[i] = G[i] = B[i] = i;
  663.       nused = 16;
  664.     }
  665.     return 0;
  666.   }
  667.   if (nused <= 32) {
  668.     for (i = 0; i < 32; i++) {
  669.       R[i] = (cusage[i].i >> 8) & 0xf;
  670.       G[i] = (cusage[i].i >> 4) & 0xf;
  671.       B[i] = cusage[i].i & 0xf;
  672.     }
  673.     return 0;
  674.   }
  675.  
  676. #if 0
  677.   nleft = nused;
  678.   for (i = nused - 1; i >= 0; i--) {
  679.     if (nleft <= 16)
  680.       break;
  681.     for (j = 0; j < i; j++)
  682.       if (rdist (i, j) + gdist (i, j) + bdist (i, j) <= 1) {
  683.         cusage[i].j = 0, nleft--;
  684.         break;
  685.       }
  686.   }
  687.   printf ("colors left %d\n", nleft);
  688. #endif
  689.  
  690.   for (i = 0, j = 0; j < 16 && i < nused; i++)
  691.     if (cusage[i].j) {
  692.       R[j] = (cusage[i].i >> 8) & 0xf;
  693.       G[j] = (cusage[i].i >> 4) & 0xf;
  694.       B[j] = cusage[i].i & 0xf;
  695.       j++;
  696.     }
  697.       
  698.   return 0;
  699. }
  700.  
  701. static int           x, y;
  702. static unsigned char r, g, b;
  703.  
  704. int
  705. display_rle (void)
  706. {
  707.   rle_hdr  rle_f_hdr;
  708.   char              *como;
  709.   int             ncolors, i, j, packed, pix, col;
  710.  
  711.   rle_f_hdr.rle_file = tfd;
  712.   if (rle_get_setup(&rle_f_hdr) < 0)
  713.     return -1;
  714.  
  715.   RLE_CLR_BIT (rle_f_hdr, RLE_ALPHA);
  716.   for (i = 3; i < rle_f_hdr.ncolors; i++)
  717.     RLE_CLR_BIT (rle_f_hdr, i);
  718.  
  719.   ncolors = rle_f_hdr.ncolors > 3 ? 3 : rle_f_hdr.ncolors;
  720.   if (ncolors == 2)
  721.     return -1;
  722.  
  723.   height = rle_f_hdr.ymax - rle_f_hdr.ymin + 1;
  724.   width  = rle_f_hdr.xmax - rle_f_hdr.xmin + 1;
  725.  
  726.   depth = 0, packed = 0;
  727.   if ((como = rle_getcom ("cy_depth", &rle_f_hdr)) != NULL) {
  728.     depth = atoi (como);
  729.     if ((como = rle_getcom ("cy_width", &rle_f_hdr)) != NULL)
  730.       width = atoi (como);
  731.     como = rle_getcom ("cy_packed", &rle_f_hdr);
  732.     packed = como ? 1 : 0;
  733.   }
  734.   if (!depth)
  735.     depth = ncolors * 8;
  736.   offsetx = (sw - width) / 2;
  737.   offsety = (sh - height) / 2;
  738.  
  739.   for (i = 0; i < 3; i++)
  740.     if ((sl[i] = (rle_pixel *) malloc(rle_f_hdr.xmax -
  741.                                       rle_f_hdr.xmin + 1)) == NULL) {
  742.       for (j = 0; j < i; j++)
  743.         free ((char *) sl[j]);
  744.       return -1;
  745.     }
  746.  
  747.   rle_f_hdr.xmax -= rle_f_hdr.xmin, rle_f_hdr.xmin = 0;
  748.  
  749.   while ((y = rle_getrow(&rle_f_hdr, sl)) <= rle_f_hdr.ymax) {
  750.     if (handleIDCMP()) {
  751.       finish();
  752.     }
  753.     y -= rle_f_hdr.ymin;
  754.     if (ncolors == 3) {
  755.       for (x = 0; x < width; x++)
  756.         r = sl[0][x], g = sl[1][x], b = sl[2][x], show_rgb ();
  757.     } else if (ncolors == 1 && !packed) {
  758.       for (x = 0; x < width; x++) {
  759.         r = cmap[0][sl[0][x]];
  760.     g = cmap[1][sl[0][x]];
  761.     b = cmap[2][sl[0][x]];
  762.     show_rgb ();
  763.       }
  764.     } else {
  765.       for (col = 0, x = 0; x < width; col = (col + 1) & 7, x++) {
  766.         pix = (sl[0][x / 8] & (1 << (7 - col))) ? 0: 255;
  767.         r = pix, g = pix, b = pix, show_rgb ();
  768.       }
  769.     }
  770.   }
  771.   for (i = 0; i < 3; i++)
  772.     free((char *) sl[i]);
  773.  
  774.   return 0;
  775. }
  776.  
  777. void
  778. show_rgb (void)
  779. {
  780.   int  xx, yy, i, j, color;
  781.   long d, td, d1, d2, d3, rd, gd, bd;
  782.  
  783.   static unsigned char pr, pg, pb;
  784.   
  785.   xx = mapx (x);
  786.   if (!flip) {
  787.     yy = mapy (y);
  788.   }else{
  789.     yy = fmapy (y);
  790.   }
  791.   if (!inside (xx, yy)){
  792.     return;
  793.   }
  794.  
  795.   if (bw) {
  796. #if 0
  797.     r = g = b = 0.35 * r + 0.55 * g + 0.10 * b;
  798. #else
  799.     r = g = b = (35 * r + 55 * g + 10 * b) / 100;
  800. #endif
  801.   }
  802. #ifndef AZTEC_C
  803.   r >>= 4, g >>= 4, b >>= 4;
  804. #else /* avoid a manx bug */
  805.   r = (r >> 4) & 0xf, g = (g >> 4) & 0xf, b = (b >> 4) & 0xf;
  806. #endif
  807.   if (threescreens) {
  808. #ifdef NOASM
  809.     OptSetAPen1 (rp1, (long) r); OptWritePixel1 (rp1, (long) xx, (long) yy);
  810.     OptSetAPen2 (rp2, (long) g); OptWritePixel2 (rp2, (long) xx, (long) yy);
  811.     OptSetAPen3 (rp3, (long) b); OptWritePixel3 (rp3, (long) xx, (long) yy);
  812. #else
  813.     MultiPlot(w1, xx, yy, r);
  814.     MultiPlot(w2, xx, yy, g);
  815.     MultiPlot(w3, xx, yy, b);
  816. #endif
  817.     return;
  818.   }
  819.   if (!isham) {
  820.     for (i = 0; i < nused; i++) {
  821.       if (R[i] == (int) r && G[i] == (int) g && B[i] == (int) b) {
  822. #ifdef NOASM
  823.         OptSetAPen1 (rp1, (long) i); OptWritePixel1 (rp1, (long) xx, (long) yy);
  824. #else
  825.     MultiPlot(w1, xx, yy, i);
  826. #endif
  827.         break;
  828.       }
  829.     }
  830.     return;
  831.   }
  832.   for (i = 0, d = MAXINT, j = -1; i < 16; i++) {
  833.     td = SQ ((long)r - (long)R[i]) +
  834.      SQ ((long)g - (long)G[i]) +
  835.      SQ ((long)b - (long)B[i]);
  836.     if (td < d)
  837.       d = td, j = i;
  838.     if (d == 0)
  839.       break;
  840.   }
  841.   if (d == 0 || x == 0) {
  842. #ifdef NOASM
  843.     OptSetAPen1 (rp1, (long) EXACT (j));
  844. #else
  845.     color = EXACT(j);
  846. #endif
  847.     pr = R[j], pg = G[j], pb = B[j];
  848.   } else {
  849.     rd = SQ ((long)r - (long)pr);
  850.     gd = SQ ((long)g - (long)pg);
  851.     bd = SQ ((long)b - (long)pb);
  852.     d1 = rd + gd, d2 = rd + bd, d3 = gd + bd;
  853.     if (d <= d1 && d <= d2 && d <= d3) {
  854. #ifdef NOASM
  855.       OptSetAPen1 (rp1, (long) EXACT (j));
  856. #else
  857.       color = EXACT(j);
  858. #endif
  859.       pr = R[j], pg = G[j], pb = B[j];
  860.     } else if (d1 <= d2 && d1 <= d3) {
  861. #ifdef NOASM
  862.       OptSetAPen1 (rp1, (long) BLUE (b));
  863. #else
  864.       color = BLUE(b);
  865. #endif
  866.       pb = b;
  867.     } else if (d2 <= d3 && d2 <= d1) {
  868. #ifdef NOASM
  869.       OptSetAPen1 (rp1, (long) GREEN (g));
  870. #else
  871.       color = GREEN(g);
  872. #endif
  873.       pg = g;
  874.     } else {
  875. #ifdef NOASM
  876.       OptSetAPen1 (rp1, (long) RED (r));
  877. #else
  878.       color = RED(r);
  879. #endif
  880.       pr = r;
  881.     }
  882.   }
  883. #ifdef NOASM
  884.   OptWritePixel1 (rp1, (long) xx, (long) yy);
  885. #else
  886.   MultiPlot(w1, xx, yy, color);
  887. #endif
  888. }
  889.  
  890. void
  891. finish(void)
  892. {
  893.   if (haveoldpri) {
  894.     SetTaskPri(FindTask(0L), oldpri);
  895.   }
  896.  
  897.   if (ifd && ifd != stdin)
  898.     fclose (ifd);
  899.  
  900.   if (tfd) {
  901.     fclose (tfd);
  902.     unlink (tfile);
  903.   }
  904.  
  905.   if (w1) {
  906.     if (w1->MenuStrip)
  907.       ClearMenuStrip(w1);
  908.     CloseWindow (w1);
  909.   }
  910.  
  911.   if (w2) {
  912.     if (w2->MenuStrip)
  913.       ClearMenuStrip(w2);
  914.     CloseWindow (w2);
  915.   }
  916.  
  917.   if (w3) {
  918.     if (w3->MenuStrip)
  919.       ClearMenuStrip(w3);
  920.     CloseWindow (w3);
  921.   }
  922.  
  923.   if (s1)
  924.     CloseScreen (s1);
  925.  
  926.   if (s2)
  927.     CloseScreen (s2);
  928.  
  929.   if (s3)
  930.     CloseScreen (s3);
  931.  
  932.   if (Ptr)
  933.     FreeMem(Ptr, POINTERSIZE * sizeof(USHORT));
  934.  
  935.   if (GfxBase)
  936.     CloseLibrary ((struct Library *)GfxBase);
  937.  
  938.   if (IntuitionBase)
  939.     CloseLibrary ((struct Library *)IntuitionBase);
  940.  
  941. #ifndef NOIFFLIB
  942.   if (IFFBase)
  943.     CloseLibrary (IFFBase);
  944. #endif
  945.  
  946.   if (AslBase)
  947.     CloseLibrary(AslBase);
  948.  
  949.   exit (0);
  950. }
  951.  
  952. UBYTE
  953. handleIDCMP(void)
  954. {
  955.   UBYTE flag = 0;
  956.   struct IntuiMessage *message;
  957.   USHORT code, selection;
  958.   ULONG class, itemnum;
  959.   int t;
  960.  
  961.   while ((message = (struct IntuiMessage *)GetMsg(w1->UserPort)) ||
  962.       (threescreens && (message=(struct IntuiMessage *)GetMsg(w2->UserPort))) ||
  963.       (threescreens && (message=(struct IntuiMessage *)GetMsg(w3->UserPort)))) {
  964.     class = message->Class;
  965.     code = message->Code;
  966.     switch (class) {
  967.       case GADGETUP:
  968.         flag = 1;
  969.         break;
  970.       case MENUVERIFY:
  971.         havemenu = 1;
  972.     FixColors();
  973.         break;
  974.       case MENUPICK:
  975.         selection = code;
  976.         while (selection != MENUNULL) {
  977.           itemnum = ITEMNUM(selection);
  978.           switch (itemnum) {
  979.             case 0:
  980.               if (ifd == stdin) {
  981.             if (threescreens) ScreenToFront(s1);
  982.         GetFile();
  983.           }else{
  984.             strcpy(fnam, infile);
  985.             t = strlen(fnam);
  986.             if ( (t >= 4) && (strcmp(&fnam[t-4], ".rle") == 0)) {
  987.               fnam[t-4] = '\000';
  988.             }
  989.             strcat(fnam, ".ilbm");
  990.           }
  991.           save();
  992.               break;
  993.             case 1:
  994.           if (threescreens) ScreenToFront(s1);
  995.           GetFile();
  996.           save();
  997.               break;
  998.             case 2:
  999.               flag = 1;
  1000.               break;
  1001.             default:
  1002.               break;
  1003.           }
  1004.           selection = ((struct MenuItem *)ItemAddress
  1005.                   (&menu, (LONG)selection))->NextSelect;
  1006.         }
  1007.         havemenu = 0;
  1008.         ResetColors();
  1009.         break;
  1010.       default:
  1011.         break;
  1012.     }
  1013.     ReplyMsg((struct Message *)message);
  1014.   }
  1015.   return flag;
  1016. }
  1017.  
  1018. void
  1019. save(void)
  1020. {
  1021. #ifndef NOIFFLIB
  1022.   char *name;
  1023.  
  1024.   if (*fnam == '\000')
  1025.     return;
  1026.  
  1027.   if (IFFBase) {
  1028.     ResetColors();
  1029.     if (threescreens) {
  1030.       name = malloc(strlen(fnam) + 4);
  1031.       if (!name) {
  1032.         fprintf(stderr, "malloc failed\n");
  1033.         return;
  1034.       }
  1035.       strcpy(name, fnam);
  1036.       strcat(name, ".r");
  1037.       IFFL_SaveBitMap
  1038.         (name, &(s1->BitMap),vp1->ColorMap->ColorTable,(isham ? 0x81 : 1));
  1039.       strcpy(name, fnam);
  1040.       strcat(name, ".g");
  1041.       IFFL_SaveBitMap
  1042.         (name, &(s2->BitMap),vp2->ColorMap->ColorTable,(isham ? 0x81 : 1));
  1043.       strcpy(name, fnam);
  1044.       strcat(name, ".b");
  1045.       IFFL_SaveBitMap
  1046.         (name, &(s3->BitMap),vp3->ColorMap->ColorTable,(isham ? 0x81 : 1));
  1047.       free(name);
  1048.     }else{
  1049.       IFFL_SaveBitMap
  1050.         (fnam, &(s1->BitMap),vp1->ColorMap->ColorTable,(isham ? 0x81 : 1));
  1051.     }
  1052.     FixColors();
  1053.   }
  1054. #endif
  1055. }
  1056.  
  1057. void
  1058. SetColor(long n, long c)
  1059. {
  1060.   long r, g, b;
  1061.  
  1062.   r = (c >> 8) & 0xf;
  1063.   g = (c >> 4) & 0xf;
  1064.   b = c & 0xf;
  1065.   SetRGB4(vp1, n, r, g, b);
  1066.   if (threescreens) {
  1067.     SetRGB4(vp2, n, r, g, b);
  1068.     SetRGB4(vp3, n, r, g, b);
  1069.   }
  1070. }
  1071.  
  1072. void
  1073. FixColors(void)
  1074. {
  1075.   struct Preferences prefs;
  1076.  
  1077.   GetPrefs(&prefs, sizeof(prefs));
  1078.   if (threescreens) {
  1079. #ifdef NOASM
  1080.     OptSetAPen1(rp1, 1L); OptSetAPen2(rp2, 1L); OptSetAPen3(rp3, 1L);
  1081. #else
  1082.     SetAPen(rp1, 1L); SetAPen(rp2, 1L); SetAPen(rp3, 1L);
  1083. #endif
  1084.     SetBPen(rp1, 0L); SetBPen(rp2, 0L); SetBPen(rp3, 0L);
  1085.   }else{
  1086. #ifdef NOASM
  1087.     OptSetAPen1(rp1, 1L);
  1088. #else
  1089.     SetAPen(rp1, 1L);
  1090. #endif
  1091.     SetBPen(rp1, 0L);
  1092.   }
  1093.   SetColor(0L, (long)prefs.color0);
  1094.   SetColor(1L, (long)prefs.color1);
  1095.   SetColor(2L, (long)prefs.color2);
  1096.   SetColor(3L, (long)prefs.color3);
  1097. }
  1098.  
  1099. void
  1100. ResetColors(void)
  1101. {
  1102.   long i;
  1103.  
  1104.   for (i=0; i<4; i++) {
  1105.     if (threescreens) {
  1106.       SetRGB4 (vp1, i,  i, 0L, 0L);
  1107.       SetRGB4 (vp2, i, 0L,  i, 0L);
  1108.       SetRGB4 (vp3, i, 0L, 0L,  i);
  1109.     }else{
  1110.       SetRGB4 (vp1, (long) i, (long) R[i], (long) G[i], (long) B[i]);
  1111.     }
  1112.   }
  1113. }
  1114.  
  1115. int
  1116. CalcWidth(int width)
  1117. {
  1118.   if (width <= 320) return 320;
  1119.   if (width <= MAX_X) return width;
  1120.   if (width <= 640) return 640;
  1121.   return width;
  1122. }
  1123.  
  1124. int
  1125. CalcHAMWidth(int width)
  1126. {
  1127.   if (width <= 320) return 320;
  1128.   return width;
  1129. }
  1130.  
  1131. int
  1132. CalcHeight(int height, int pal)
  1133. {
  1134.   if (pal) {
  1135.     if (height <= 256) return 256;
  1136.     if (height <= MAX_Y_PAL) return height;
  1137.     if (height <= 512) return 512;
  1138.     return height;
  1139.   }else{
  1140.     if (height <= 200) return 200;
  1141.     if (height <= MAX_Y_NTSC) return height;
  1142.     if (height <= 400) return 400;
  1143.     return height;
  1144.   }
  1145. }
  1146.  
  1147. void
  1148. GetFile(void)
  1149. {
  1150.   struct FileRequester *freq;
  1151.   int tmp;
  1152.  
  1153.   FileReqTags[WINTAG].ti_Data = (ULONG)w1;
  1154.   freq = AllocAslRequest(ASL_FileRequest, FileReqTags);
  1155.   if (!freq){
  1156.     fprintf(stderr, "Can't allocate file requester\n");
  1157.     return;
  1158.   }
  1159.   FixColors();
  1160.   tmp = AslRequest(freq, NULL);
  1161.   ResetColors();
  1162.   fnam[0] = '\000';
  1163.   if (tmp && freq->fr_File[0]) {
  1164.     strcpy(fnam, freq->fr_Drawer);
  1165.     tmp = strlen(fnam) - 1;
  1166.     if (tmp >= 0 && fnam[tmp] != '/' && fnam[tmp] != ':'){
  1167.       strcat(fnam, "/");
  1168.     }
  1169.     strcat (fnam, freq->fr_File);
  1170.   }
  1171.   FreeAslRequest(freq);
  1172.   return;
  1173. }
  1174.  
  1175. /*
  1176.    No-one in his right mind would want to run this program from the Workbench!
  1177. */
  1178. #ifndef __SASC
  1179. #ifndef __GNUC__
  1180. void
  1181. _wb_parse(void)
  1182. {}
  1183. #endif
  1184. #endif
  1185.